package com.sl.transport.repository.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.sl.transport.domain.OrganDTO;
import com.sl.transport.enums.OrganTypeEnum;
import com.sl.transport.repository.OrganRepository;
import org.neo4j.driver.internal.InternalPoint2D;
import org.neo4j.driver.types.Node;
import org.springframework.data.neo4j.core.Neo4jClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;

@Service
public class OrganRepositoryImpl implements OrganRepository {

    @Resource
    private Neo4jClient neo4jClient;

    /**
     * 无需指定type，根据id查询
     *
     * @param bid 业务id
     * @return 机构数据
     */
    @Override
    public OrganDTO findByBid(Long bid) {
        String cypher = StrUtil.format("match (n) where n.bid={} return n", bid);
        return CollUtil.getFirst(executeQuery(cypher));
    }

    /**
     * 无需指定type，根据ids查询
     *
     * @param bids 业务id
     * @return 机构数据
     */
    @Override
    public List<OrganDTO> findByBids(List<Long> bids) {
        String cypher = StrUtil.format("match (n) where n.bid in {} return n", bids);
        return executeQuery(cypher);
    }

    /**
     * 查询所有的机构，如果name不为空的按照name模糊查询
     *
     * @param name 机构名称
     * @return 机构列表
     */
    @Override
    public List<OrganDTO> findAll(String name) {
        String cypher = StrUtil.isBlank(name)
                ? StrUtil.format("match (n) return n")
                : StrUtil.format("match (n) where n.name contains '{}' return n", name);
        return executeQuery(cypher);
    }

    /**
     * 执行查询语句
     *
     * @param cypherQuery 查询语句
     * @return 机构集合
     */
    private List<OrganDTO> executeQuery(String cypherQuery) {
        Collection<OrganDTO> collection = neo4jClient.query(cypherQuery)
                .fetchAs(OrganDTO.class)
                .mappedBy(((typeSystem, record) -> {
                    Map<String, Object> map = record.get(0).asMap();
                    //获取所有节点
                    Node node = record.get(0).asNode();
                    OrganDTO organDTO = BeanUtil.toBeanIgnoreError(map, OrganDTO.class);
                    //补充类型
                    organDTO.setType(OrganTypeEnum.valueOf(CollUtil.getFirst(node.labels())).getCode());
                    //补充经纬度
                    InternalPoint2D location = (InternalPoint2D) map.get("location");
                    if (ObjectUtil.isNotEmpty(location)) {
                        organDTO.setLongitude(location.x());
                        organDTO.setLatitude(location.y());
                    }
                    return organDTO;
                })).all();
        //将Collection转为List
        return ListUtil.toList(collection);
    }

}
